﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Windows.Data;
using System.Windows.Controls.Primitives;

namespace RadiantQCommunityControls
{
    public static class Extensions
    {
        /// <summary>
        /// Finds an ancestor of the specified type.
        /// </summary>
        /// <typeparam name="T">The type of the ancestor</typeparam>
        /// <param name="obj">The DependencyObject whole ancestor we want to find.</param>
        /// <returns>The ancestor of the specified type.</returns>
        public static T FindAncestor<T>(DependencyObject obj) where T : DependencyObject
        {
            while (obj != null)
            {
                T o = obj as T;
                if (o != null)
                    return o;
                obj = VisualTreeHelper.GetParent(obj);
            }
            return null;
        }

        /// <summary>
        /// Finds an ancestor of the specified type.
        /// </summary>
        /// <typeparam name="T">The type of the ancestor</typeparam>
        /// <param name="obj">The UIElement whole ancestor we want to find.</param>
        /// <returns>The ancestor of the specified type.</returns>
        public static T FindAncestor<T>(this UIElement obj) where T : UIElement
        {
            return FindAncestor<T>((DependencyObject)obj);
        }

        /// <summary>
        /// Gets children of a specific Type.
        /// </summary>
        /// <typeparam name="T">The type of children.</typeparam>
        /// <param name="parent">The parent whose children we want to find.</param>
        /// <param name="children">The list which will contain the matched children.</param>
        /// <param name="recurseThroughMatches">Specifies if the we should continue searching inside a matched element.</param>
        /// <param name="onlyVisible">true to only find visible elements.</param>
        public static void GetChildren<T>(DependencyObject parent, ref List<T> children, bool recurseThroughMatches, bool onlyVisible)
            where T : UIElement
        {
            int count = VisualTreeHelper.GetChildrenCount(parent);
            if (count > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                    if (child is T)
                    {
                        T uiElement = child as T;
                        if (onlyVisible == false || uiElement.Visibility == Visibility.Visible)
                        {
                            children.Add(uiElement);
                            if (recurseThroughMatches == false)
                                continue;
                        }
                    }
                    GetChildren<T>(child, ref children, recurseThroughMatches, onlyVisible);
                }
            }
        }
    }
    public class ScrollValueTracker : FrameworkElement, IDisposable
    {
        public ScrollValueTracker(ScrollBar vertScrollBar)
        {
            Binding binding = new Binding("Value");
            binding.Source = vertScrollBar;
            this.SetBinding(ValueProperty, binding);
        }

        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(ScrollValueTracker), new PropertyMetadata(0.0, BoundValueChangedCallback));

        private static void BoundValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ScrollValueTracker)d).OnValueChanged();
        }

        internal void OnValueChanged()
        {
            if (this.ValueChanged != null)
                this.ValueChanged(this, EventArgs.Empty);
        }

        public event EventHandler ValueChanged;

        #region IDisposable Members

        public void Dispose()
        {
            this.ClearValue(ValueProperty);
        }

        #endregion
    }
    
}
